import sys
import time


class ProgressBar:
    progress: int = 0  # 0 to 100
    first_output: bool = True

    def __init__(self, templete="[{bar}] {prog}%", barlen=20, p_templete=("#", " ")) -> None:
        self.templete: str = templete
        self.p_templete: tuple[str, str] = p_templete
        self.barlen: int = barlen  # char

    def ref_prog(self) -> None:
        prog_slen = int(self.barlen*self.progress/100)
        prog_text = (self.p_templete[0])*prog_slen + \
            (self.p_templete[1])*(self.barlen-prog_slen)
        print_text = self.templete.format(bar=prog_text, prog=self.progress)
        if not self.first_output:
            sys.stdout.write("\033[1A")
        else:
            self.first_output = False
        sys.stdout.write(print_text)
        sys.stdout.write('\n')

    def set(self, progress) -> None:
        self.progress = progress
        self.ref_prog()


class ProgressPoint:
    first_output: bool = True
    animation_flash: int = 0

    def __init__(self, templete="{bar}", p_templete=("⠋", "⠙", "⠸", "⠴", "⠦", "⠇"), stop_templete="⠿") -> None:
        self.templete: str = templete
        self.p_templete: tuple[str, str] = p_templete
        self.stop_templete = stop_templete

    def ref_prog(self) -> None:
        print_text = self.templete.format(
            bar=self.p_templete[self.animation_flash])
        self.animation_flash += 1
        if self.animation_flash == len(self.p_templete):
            self.animation_flash = 0
        if not self.first_output:
            sys.stderr.write("\033[1A")
        else:
            self.first_output = False
        sys.stderr.write(print_text)
        sys.stderr.write('\n')

    def stop(self) -> None:
        self.p_templete = (self.stop_templete,)
        self.animation_flash = 0
        self.ref_prog()

    def wait_in_anim(self, wait_time: int = 0.1, check_func=lambda n: n < 50) -> None:
        num: int = 0
        while 1:
            self.ref_prog()
            time.sleep(wait_time)
            ret = check_func(num)
            if ret == False:
                break
            num += 1
        self.stop()
